package com.moli.iov.admin.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.io.FileUtil;
import com.aliyun.oss.OSSClient;
import com.moli.iov.admin.config.AliyunConfig;
import com.moli.iov.admin.model.vo.req.UploadVo;
import com.moli.iov.admin.service.IUploadService;
import com.moli.iov.rest.RestResponse;
import com.moli.iov.util.PdfToImageUtil;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Date;
import java.util.Random;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

/**
 * <p>
 * OSS 文件上传
 * </p>
 *
 * @author zql
 * @since 2019/9/10 11:16
 */
@Slf4j
@Service
public class UploadServiceImpl implements IUploadService {

  /**
   * 允许上传的格式
   */
  private static final String[] IMAGE_TYPE = new String[]{"pdf"};

  @Autowired
  private OSSClient ossClient;

  @Autowired
  private AliyunConfig aliyunConfig;

  /**
   * 文件目录
   */
  private static  final String PIC_PATH_DIR = "images";

  private static final String PIC_SUFFIX = "png";

  /**
   * pdf路径
   */
  private static final  String PDF_PATH_DIR = "pdf";

  private static final String PDF_SUFFIX = "pdf";

  /**
   * OSS上传
   * @param uploadFile
   * @return
   */
  @Override
  public RestResponse upload(MultipartFile uploadFile) throws IOException {

    //图片做校验，对后缀名
    boolean isLegal = false;

    for (String type : IMAGE_TYPE) {
      if (StringUtils.endsWithIgnoreCase(uploadFile.getOriginalFilename(),
          type)) {
        isLegal = true;
        break;
      }
    }

    if (!isLegal) {
      return RestResponse.failure("图片格式不正确");
    }

    //上传pdf
    String pdfFilePath = getFilePath(PDF_PATH_DIR, PDF_SUFFIX);
    String pdfUrl = ossUpload(pdfFilePath, uploadFile.getBytes());

    //上传图片
    byte[] image = getImageByte(uploadFile);
    String picFilePath = getFilePath(PIC_PATH_DIR, PIC_SUFFIX);
    String picUrl = "";
    if(image != null){
      picUrl = ossUpload(picFilePath, image);
    }

    return RestResponse.success(new UploadVo(picFilePath, picUrl, pdfFilePath, pdfUrl));
  }

  /**
   * 上传oss
   * @param filePath
   * @param data
   * @return
   */
  public String ossUpload(String filePath, byte[] data){
    try {

      ossClient.putObject(aliyunConfig.getBucketName(), filePath, new
          ByteArrayInputStream(data));

    } catch (Exception e) {
      log.error("上传失败", e);
    }

    String picUrl = getUrl(filePath);
    log.info("图片路径：{}", picUrl);

    return picUrl;
  }

  /**
   * pdf转image 返回image 字节
   * @param uploadFile
   * @return
   */
  public byte[] getImageByte(MultipartFile uploadFile){
    try {
      File pdfF = multipartFileToFile(uploadFile);
      String pefPath = pdfF.getAbsolutePath();
      String imgPath = PdfToImageUtil.pdfToImage(pefPath);
      return FileUtil.readBytes(imgPath);
    } catch (Exception e) {
      log.error("pdf转image 返回image 字节 异常", e);
      return null;
    }
  }

  /**
   * 目录结构：images/2019/10/29/xxxx.jpg
   * @param suffix
   * @return
   */
  private String getFilePath(String baseDir, String suffix) {
    DateTime dateTime = new DateTime();
    return PIC_PATH_DIR + "/" + dateTime.toString("yyyy")
        + "/" + dateTime.toString("MM") + "/"
        + dateTime.toString("dd") + "/" + System.currentTimeMillis() +
        RandomUtils.nextInt(new Random(100), 9999) + "." + suffix;
  }

  /**
   * 获取OSS签名
   * @return
   */
  public String getUrl(String key){
    // 设置URL过期时间为10年  3600l* 1000*24*365*10
    Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000 * 24 * 365 * 10);
    //生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
    URL url = ossClient.generatePresignedUrl(aliyunConfig.getBucketName(), key, expiration);
    return url.toString();
  }

  /**
   * MultipartFile 转 File
   * @param file
   * @throws Exception
   */
  public static File multipartFileToFile(MultipartFile file) throws Exception {
    File toFile = null;
    if (file.equals("") || file.getSize() <= 0) {
      file = null;
    } else {
      InputStream ins = null;
      ins = file.getInputStream();
      toFile = new File(file.getOriginalFilename());
      inputStreamToFile(ins, toFile);
      ins.close();
    }
    return toFile;
  }

  public static void inputStreamToFile(InputStream ins, File file) {
    try {
      OutputStream os = new FileOutputStream(file);
      int bytesRead = 0;
      byte[] buffer = new byte[8192];
      while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
        os.write(buffer, 0, bytesRead);
      }
      os.close();
      ins.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
